---
--类名: Mercenary.lua
--创建日期: 2015-6-9
--创建人: 陈小虎
--功能描述: 佣兵模型
--修改内容：
--修改日期:   
--修改人:     
--修改备注: 
--
local Role = import(".Role")

local Mercenary = class("Mercenary",function()
    return Role.new()--display.newNode()
end)

Mercenary.ACTION_MAP_IDLE = "mapidle"
Mercenary.ACTION_MAP_MOVE = "mapmove"
Mercenary.ACTION_MAP_MOVE_STOP = "mapmovestop"

local NodeSetLocalZOrderFunc = cc.Node.setLocalZOrder
local NodeGetLocalZOrderFunc = cc.Node.getLocalZOrder


function Mercenary:ctor(id, pId, isSyncLoad, isPartner)
	self:setId(pId)
    self.resId = id

    if isPartner then
        local Partner = require("app.public.dao.Partner")
        self._partner = Partner.new()
        self._partner:initWithId(pId)
    end

    self.isUseAsyncLoad = true
    if isSyncLoad then 
        self.isUseAsyncLoad = false
    end

    self.mArmParent = display.newNode()
    self.mArmParent:setCascadeColorEnabled(true)
    self.mArmParent:setCascadeOpacityEnabled(true)
    self:addChild(self.mArmParent)

    self:buildArmatureNode()

	self:scheduleUpdate( handler(self, self.updateFrame))
    
    self:setNodeEventEnabled(true)
end

function Mercenary:onEnter()

end

function Mercenary:onExit()

end

function Mercenary:onArmatureLoad()
    local AvatarFactory = app:getClass("AvatarFactory")
    local mArmatrueNode
    if self._partner then
        mArmatrueNode = AvatarFactory.createPartnerByConf(self._partner:getShowAvatorParams())
    else
        mArmatrueNode = AvatarFactory.createNpcById(self.resId)
    end
    self.mArmatrueNode = mArmatrueNode
    self.mArmatrueNode:setAutoPlaySound(false)
    self.mArmParent:addChild(self.mArmatrueNode)

    self:playAction(Role.ACTION_MAP_IDLE)
end

function Mercenary:buildArmatureNode()
    if not self.isUseAsyncLoad then
        self:onArmatureLoad()
        return
    end
    local AvatarFactory = app:getClass("AvatarFactory")
    
    if self._partner then
        AvatarFactory.preloadPartnerByConf(self._partner:getShowAvatorParams(), function()
            if tolua.isnull(self) then return end
            self:onArmatureLoad()
        end)
    else
        AvatarFactory.preloadNpcById(self.resId, function()
            if tolua.isnull(self) then return end
            self:onArmatureLoad()
        end)
    end
end

function Mercenary:setNodeVisible(visible)
    self:setVisible(visible)

    if self.mHeadNameNode then
        self.mHeadNameNode:setVisible(visible)
    end
end

function Mercenary:removeAll()
    if self.m_markNode then
        self.m_markNode:removeFromParent()
        self.m_markNode = nil
    end
    if self.m_bubble then
        self.m_bubble:removeFromParent()
        self.m_bubble = nil
    end
    if self.mHeadNameNode then
        self.mHeadNameNode:removeFromParent()
        self.mHeadNameNode = nil
    end
end

function Mercenary:getSelfScale()
    if not self.mArmatrueNode then return 1.0 end
    return self.mArmatrueNode:getScaleY()
end

function Mercenary:getPointPosition()
    local x,y = -1000,-1000
    if self.mArmatrueNode then 
        x,y = self:getCCSlotPointPosition(self.mArmatrueNode)
        
        y = y * self:getSelfScale()
        x = 0   
    end
    return x,y
end

function Mercenary:setMarkNode(markNode)
    if not markNode then return end
    self.m_markNode = markNode
    local x,y = self:getPointPosition()
    self.m_markX = x
    self.m_markY = y
end

function Mercenary:markNodeVisiblity(visible)
    if not self.m_markNode then return end
    if not self.m_showBubble then
        self.m_markNode:setVisible(visible)
    elseif not visible then
        self.m_markNode:setVisible(visible)
    end
end

function Mercenary:updateMarkPosition()
    -- if self:getAction() ~= Role.ACTION_MAP_MOVE then return end
    if not self.m_markNode then return end

    local convertPosX,convertPosY = self.mArmParent:toWorldPosition(self.m_markX,self.m_markY)
    self.m_markNode:setPosition(convertPosX,convertPosY)

    if self.m_bubble and self.m_bubble:isVisible() then
        self.m_bubble:showLocation(convertPosX,convertPosY)
    end

end

-- 更新 mHeadNameNode 的坐标
function Mercenary:updateHeadNamePosition()
    -- if self:getAction() ~= Role.ACTION_MAP_MOVE then return end
    if self.mArmatrueNode then
        local xx, yy = self.mArmatrueNode:getBoneWorldPosition("point")
        if self.mHeadNameNode then 
            self.mHeadNameNode:setPosition(xx, yy)
        end
    end

end

function Mercenary:setBubble(bubble,callback)
    if self.m_bubble then
        self.m_bubble:removeFromParent()
        self.m_bubble = nil
    end
    self.m_bubble = bubble

    self.m_bubble:setTouchEndCallback(function()
        if callback then
            callback()
        end
    end)
    self:hideBubble()
end

function Mercenary:hideBubble()
    if self.m_bubble then
        self.m_showBubble = false
        self.m_bubble:stopAllActions()
        self.m_bubble:hide()
        self.m_bubble:removeFromParent()
        self.m_bubble = nil
    end
end

function Mercenary:showBubble(content,showTime,overCall)
    if not self.mArmatrueNode then return end
    if string.len(content) <= 0 then return end
    if cc.isDead(self.m_bubble) then
        self.m_bubble = NodeFactory:createBubble()
    end
--    if self.m_bubble then
        self.m_showBubble = true
        self:markNodeVisiblity(false)
        self.m_bubble:stopAllActions()
        local x,y = self.mArmParent:toWorldPosition(self.m_markX,self.m_markY)

        self.m_bubble:showLocation(x,y)
        self.m_bubble:setContent(content)
        self:transitionBubble()
        self.m_bubble:runAnimation()
        
        if StoryManager:isEnterStoryMode() then
            self.m_bubble:getParent():reorderChild(self.m_bubble,SceneZOrder.storyModeUIOperateZOrder)
        else
            self.m_bubble:getParent():reorderChild(self.m_bubble,SceneZOrder.systemUIZOrder - 1)
        end

        local function callback()
            self.m_showBubble = false
            self:markNodeVisiblity(true)
            self:hideBubble()
            if overCall then
                overCall()
            end
        end
        local action = cc.Sequence:create(cc.DelayTime:create(tonumber(showTime)),cc.CallFunc:create(callback))
        self.m_bubble:runAction(action)

        if DEBUG == -1 then
            self.m_bubble:setVisible(false)
        end
--    end
end

function Mercenary:transitionBubble()
    if not self.mArmatrueNode then return end
    local flipX = self.mArmatrueNode:getScaleX()
    if self.m_bubble then
        if flipX > 0 then
            self.m_bubble:faceToRight()
        else
            self.m_bubble:faceToLeft()
        end
    end
end

function Mercenary:setName(name)
    if not name then return end
    if not self.mHeadNameNode then return end
    if self.mName == name then return end

    self.mName = name
    self.mHeadNameNode:setName(L(name))
end

function Mercenary:setNameNode(nameNode)
    assert(nameNode)
    assert(self.mHeadNameNode == nil)
    self.mHeadNameNode = nameNode

    self:setName("")
    -- self:setTitle("")
    -- self:setGuildName("")
    -- self:toNormalColor()

    -- 查找name
    local npcConfig = GD:queryMapsetShowById(self:getId())
    if npcConfig then
        self:setName(npcConfig.name)
    end

    self.mHeadNameNode:setNameColor(Res.PlayerNameColors.Self)
    self:addAttachment(nameNode, "point", 0, 0)
end

function Mercenary:setLine(line)
    Role.setLine(self,line)
    self:updateNameZOrder()
end

function Mercenary:updateNameZOrder()
    local headNameNode = self.mHeadNameNode
    if  headNameNode then
        local line = self:getLine()
        local zOder = line*100 + NodeGetLocalZOrderFunc(self)
        NodeSetLocalZOrderFunc(headNameNode,zOder)
    end
end

function Mercenary:setBelongUid(uid)
    self.mBelongUid = uid
end

function Mercenary:getBelongUid()
    return self.mBelongUid
end

function Mercenary:setRunStop(runStop)
    self.mRunStop = runStop
end

function Mercenary:isRunStop()
    return self.mRunStop
end


function Mercenary:scaleTo(scale)
    self.mArmParent:setScale(scale)
end

function Mercenary:move()
    if self:getAction() ~= Role.ACTION_MAP_MOVE then
        self:playAction(Role.ACTION_MAP_MOVE)
    end
end

function Mercenary:standby()
    if self:getAction() ~= Role.ACTION_MAP_IDLE then
        self:playAction(Role.ACTION_MAP_IDLE)
    end
end

function Mercenary:faceToLeft()
    self:setDirection(Role.DIR_LEFT)
    if self.mArmatrueNode then
        local scale = self.mArmatrueNode:getScaleX()
        self.mArmatrueNode:setScaleX(math.abs(scale))
    end
end

function Mercenary:faceToRight()
    self:setDirection(Role.DIR_RIGHT)
    if self.mArmatrueNode then
        local scale = self.mArmatrueNode:getScaleX()
        self.mArmatrueNode:setScaleX(-math.abs(scale))
    end
end

function Mercenary:setTargetX(tarX)
	self.mTargetX = math.floor(tarX)
end

function Mercenary:showLocationX(x)
    self:setTargetX(x)
    self:rayCastFoothold(x)
end

function Mercenary:setLeaderCharacter(leader)
    self.mLeaderCharacter = leader
end

function Mercenary:playAction(action,callback)
    if self.mAction == action then return end
    if not self.mArmatrueNode then 
        if callback then
            callback()
        end
        return 
    end
    self.mAction = action
    if callback then
        self.mArmatrueNode:playAni({name = action,completeCallback = callback})
    else
        self.mArmatrueNode:playAni({name = action})
    end
    
end

function Mercenary:playRunstopAction(action,callback)
    self.mAction = action
end


function Mercenary:getAction()
    return self.mAction
end

function Mercenary:excuteAction(action)
    self:runAction(action)
    if self.mHeadNameNode then
        self.mHeadNameNode:runAction(action:clone())
    end
end

function Mercenary:syncDirection()
    if not self.mLeaderCharacter then return end
    
    if self.mLeaderCharacter:getDirection() == Role.DIR_LEFT then
        self:faceToLeft()
    else
        self:faceToRight()
    end
end

function Mercenary:onStopMove()
    self:standby()
    self:syncDirection()
end

function Mercenary:updateFrame(dt)
    self:updateMarkPosition()
    self:updateHeadNamePosition()

	local curPosXFloat, curPosY = self:getPosition()
    local curPosX = math.floor(curPosXFloat)
    local targetX = self.mTargetX or curPosX -- mTargetX 取值为整数

    if targetX ~= curPosX then
        
        if curPosX < targetX then
            self:faceToRight()
        else
            self:faceToLeft()
        end

        if self:getAction() ~= self.ACTION_MAP_MOVE_STOP then
            self:move()
        end

        local disX = self:getSpeed() * dt

        local newX = curPosXFloat + disX * self:getDirection()

        if self:getDirection() == Role.DIR_LEFT then
            if newX < targetX then
                newX = targetX
            end
        else
            if newX > targetX then
                newX = targetX
            end
        end

        self:rayCastFoothold(newX)
    else
        if self:getAction() ~= self.ACTION_MAP_MOVE_STOP then
            self:onStopMove()
        end

        self:syncDirection()
    end
end

function Mercenary:rayCastFoothold(newX)
    local standY = MapManager:getStandPointY(self:getLine(),math.floor(newX)) or 0

    self:showLocation(newX, standY)
end



return Mercenary